package TuiLayer;
import java.util.Scanner;
import ControlLayer.*;
/**TuiLayer package sets the location for AddressBookUI class.
 * 
 * Scanner package is used here, because it provides tracking on the inputs from a
 * keyboard. This gives user(Private Person) the ability to have control on
 * AddressBookUI. The control is exercised by inserting different values through the
 * keyboard. This means that AddressBookUI behaves strictly in accordance to the user
 * preferences.
 * 
 * The ControlLayer package is imported, because TUIs must be able to access classes
 * in the ControlLayer - AddressController, RegisterController and LoanController.
 * ---------------------------------------------------------------------------------
 * AddressBookUI class is devided in 6 sections. In each section(except the first
 * one) methods with similar functionalities are placed.
 * 
 * Section Contents:
 *  Variables
 *  Constructors
 *      - AddressBookUI()
 *      - start()
 *  UserTrackers
 *      - addressMenu()
 *      - writeAddressBookMenu()
 *  Methods
 *      - getPerson()
 *      - addPerson()
 *      - deletePerson()
 *      - update()
 *      - listAllPersons()
 *  Inputs
 *      - inputContinue()
 *      - inputPersonsID()
 *      - inputName()
 *      - inputAddress()
 *      - inputPostalCode()
 *      - inputCity()
 *      - inputPhone()
 *  Printers
 *      - writeError()
 *      - writeNotFound()
 */

public class AddressBookUI
{
  /** VARIABLES */
    //AddressBookUI has to send the user preferences as commands to AddressController.
    //For the purpose to provide access to the controller, the following object
    //reference(association) is needed.
    private AddressController tellCtr;  //Reference to AddressController.
    
  /** CONSTRUCTORS */
  public AddressBookUI()
  //Creates an instance of AddressBookUI class.
  {
      tellCtr = new AddressController();
      //Initializes a new AddressController.
  }
  
  public void start()
  //Launches the UI and initializes the optionChoice functionality. User is
  //now able to use the AddressBookUI.  
  {
      addressMenu();    //See User Tracker section.
  }
  
  /** USER TRACKERS */
  public void addressMenu()
  //Provides the optionChoice functionality.
  {
      boolean isRunning = true;
      //This indicates whether the UI is launched and running.
      
      while(isRunning)
      //This can be interpreted like this: 'While the application is running perform
      //the following tasks below'. If the boolean expression isRunning becomes
      //false, then the interface stops working and the application is closed. User
      //cannot use the AddressBook anymore and goes back to MainMenu interface.
      {
          int optionChoice = writeAddressBookMenu();
          //Before determing what the UI have to execute, it will acquire user
          //optionChoice first, by calling this method.
          
          if(optionChoice == 1)
          //User inputs 1 as an optionChoice - UI prompts user for person details.
          {
              addPerson();
          }  
          
          else if(optionChoice == 2)
          //User inputs 2 as an optionChoice - UI prompts user for input values
          //for attributes to determine searching details.
          {
              getPerson();
          }
          
          else if(optionChoice == 3)
          //User inputs 3 as an optionChoice - UI update a person chosen by user.
          {
              update();
          }
          
          else if(optionChoice == 4)
          //User inputs 4 as an optionChoice - UI deletes a person chosen by user.
          {
              deletePerson();
          }  
          
          
          else if(optionChoice == 5)
          //User inputs 5 as an optionChoice - UI displays a list of all persons.
          {
              listAllPersons(); 
          }
          
          else if(optionChoice == 0)
          //User inputs 0 as an optionChoice -  User is redirected back to the
          //MainMenuUI. 
          {
              isRunning = false;   //Variable isRunning becomes false. UI shuts down.
          }
                          
          else if(optionChoice != 1 && optionChoice != 2 && optionChoice != 3
                  && optionChoice != 4 && optionChoice != 5 && optionChoice !=0)
          //This checks whether the optionChoice number is a valid command. User 
          //makes invalid input(the number is not within the range from 0 to 5).
          //A message is displayed to notify about the problem.            
          {
              writeError(); 
              inputContinue();
          }
            
      }
  }

  public int writeAddressBookMenu()
  //Acquires optionChoice. It creates a keyboard object(of Scanner class), so 
  //that user can input her optionChoice. It is important to note that this
  //method also visualizes the UI.
  {
      Scanner keyboard = new Scanner(System.in);
      //Creates the keyboard object.
            
      System.out.println("\f *** Address Book Menu ***");
      System.out.println("  (1) Add New Person");
      System.out.println("  (2) Show Person Details");
      System.out.println("  (3) Update Person Details");
      System.out.println("  (4) Remove Person");
      System.out.println("  (5) List All Persons");
      System.out.println("  (0) Return to Main Menu");
      System.out.print("\n Choose an option: ");
      //AddressBookUI visualization. It is made by printing these lines in the
      //Terminal window.
      
      String checkInput = keyboard.nextLine();
      //This tracks user inputs by calling Scanner nextLine() method on each input.
      
      int optionChoice; //Local variable, where user option choice will be stored.
      
      try
      //After getting user input, this try-catch structure checks whether the
      //input is a number(integer). This allows the use of integers, instead of 
      //strings for determing the user option choice and at the same time this
      //prevents system from crashing.
      {
          optionChoice = Integer.parseInt(checkInput);
          //If it is a number then UI gets an optionChoice to check whether it
          //there is such an option.
      }
      
      catch(NumberFormatException wrongInput)
      {
          optionChoice = -1;
          //If the input is not a number, then this code will make UI display a
          //message, to notify user about the problem.
      }
      
      return optionChoice; //Sends what is the user optionChoice.
  }
  
  /** METHODS */
  private void getPerson()
  //Defines searching details in accordance to user preferences.
  {
      String id = inputPersonsID();
      //Variable id is the definition for user search criteria.
      
      try
      //This try-catch structure ensures that the system will not crash. So, if
      //there is a person with the requested(by user) id it will be displayed.
      //Otherwise it will display a message that nothing is found.
      {
          System.out.println(tellCtr.printPerson(id)); 
          //Tells the Controller to show user the search results.
          
          inputContinue();
      }
      catch(NullPointerException notFound)
      {
          writeNotFound();
          //Displays the reason why there is no search result.
          
          inputContinue();
      }
  }
  
  private void addPerson()
  //Prompts user to add attributes for the Person which is going to be
  //added(created) in the AddressBook.
  {
        String id = "";
        String name = "";
        String address = ""; 
        String postalCode = "";
        String city = "";
        String phone = "";
        
        id = inputPersonsID();
        name = inputName();
        address = inputAddress();
        postalCode = inputPostalCode();
        city = inputCity();
        phone = inputPhone();
        //For each variable, UI prompts first for a value, then user has to
        //input it. After all attributes are done, person is added in the
        //AddressBook.
        
        tellCtr.createPerson(id, name, address, postalCode, city, phone);
        //Tells the Controller to add the person to the AddressBook with user
        //defined attributes.
        
        inputContinue();
  }
    
  public void deletePerson()
  //Prompts user to add attribute for id. If the id is valid then a person with
  //such an id will be removed from the AddressBook.
  {
      String delete = inputPersonsID();
      //Defines which person will be removed.
      
      try 
      //This try-catch structure ensures that the system will not crash. So, if
      //there is a person with the requested(by user) id it will be removed.
      //Otherwise it will display a message that there is no person with such id.
      {
          tellCtr.deletePerson(delete);
          //Tells Controller to remove the person.
          System.out.println(" Person has been removed successfully. \n");
          //Notifies user for the successful execution of the operation.
      }
      catch(Exception notFound)
      {
          writeNotFound();
      }
      
      inputContinue();
  }
  
  public void update()
  //Prompts user to add attribute for id. If the id is valid then user 
  //will be allowed to change attributes of a person with such an id.
  {
      String id= inputPersonsID();
      //Defines which person's details will be updated.
      
      try
      //This try-catch structure ensures that the system will not crash. So, if
      //there is a person with the requested, user will be allowed to add the new
      //attributes for the person. Otherwise it will display a message that there
      //is no person with such id.
      {
          tellCtr.updatePerson(id,inputName(), inputAddress(), inputPostalCode(), 
          inputCity(), inputPhone());
          //Tells controller to change person attributes.
          System.out.println(" Person details have been updated successfully.\n");
          //Notifies user for the successful execution of the operation.
      }
      catch(Exception notFound)
      {
          writeNotFound();
      }
      inputContinue();
  }
  
  public void listAllPersons()
  //Displays a list of all persons in the AddressBook.
  {
      int index=0;
      while(index<tellCtr.listAllPersons().size())
      //This while will print persons and stop when it will reach the last person
      //in the AddressBook.
      {
          System.out.println(tellCtr.listAllPersons().get(index).toString());
          index++;
          System.out.println();
      }
      
      //Prints listAllPerson found entry results.
      if(index >= 2)
      {
          System.out.println("Found " + index + " entries.");
      }
      else if(index == 1)
      {
          System.out.println("Found " + index + " entry.");
      }
      else
      {
          System.out.println("Found no entries.");
      }
      System.out.println("\n");

         
      inputContinue();
  }
  
  /** INPUTS */
  public void inputContinue()
  //Prompts user to press Enter to continue using the UI.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Press Enter to continue. ");
      String code = keyboard.nextLine();
  }
  
  public String inputPersonsID()
  //Prompts user to define a value for PersonID.
  {
      boolean stop = false;
      //This boolean controls the while loop, which is waiting for the user input.
      //When it becomes true, while stops.
      String id = "";
      
      while(!stop)
      {
          Scanner keyboard = new Scanner(System.in);
          System.out.println(" Write Id: ");
          try
          {
              id = keyboard.nextLine();
              stop = true;
          }
          catch (Exception isNotNumber)
          {
              System.out.println(" It should be a number. Try again!\n");
              String input = keyboard.nextLine();
          }
   
      }
      
      return id;
  }
  
  public String inputName()
  //Prompts user to define a value for name.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Write Name: ");
      String name = keyboard.nextLine();
      return name;
  }
 
    public String inputAddress()
  //Prompts user to define a value for address.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Write Address: ");
      String address = keyboard.nextLine();
      return address;
  }
  
  public String inputPostalCode()
  //Prompts user to define a value for postalCode.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Write Postal Code: ");
      String code = keyboard.nextLine();
      return code;
  }
  
  public String inputCity()
  //Prompts user to define a value for city.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Write City: ");
      String city = keyboard.nextLine();
      return city;
  }
  
  public String inputPhone()
  //Prompts user to define a value for phone.
  {
      Scanner keyboard = new Scanner(System.in);
      System.out.println(" Write Phone Number: ");
      String phone = keyboard.nextLine();
      return phone;
  }
  
  /** PRINTERS */
  private void writeError()
  //Prints an error message in the terminal window.
  {
      System.out.println("\n [ERROR]:\n You can only insert\n numbers 1, 2, 3 , 4"
                                + " 5\n and 0 for an option choice."
                                + "\n");
      inputContinue();
  }
  
  private void writeNotFound()
  //Prints an error message in the terminal window.
  {
      System.out.println("\n[ERROR]:\nThere is no person with such an ID\n");
  }
}
